using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using IQIGame.Onigao.GameAOT;
using UnityEngine;
using UnityEngine.Rendering;

namespace IQIGame.Onigao.GamePlay
{
    public class HUDNumberRender
    {
        static HUDNumberRender s_pHUDNumberRenderIns = null;

        public static HUDNumberRender Instance
        {
            get
            {
                if (s_pHUDNumberRenderIns == null)
                {
                    s_pHUDNumberRenderIns = new HUDNumberRender();
                }

                return s_pHUDNumberRenderIns;
            }
        }

        public CommandBuffer GetCmdBuffer()
        {
            return s_cmdBuffer;
        }

        bool m_bAddCommandBuffer = false;

        HUDNumberEntry m_aInvalid;
        float m_fDurationTime => HUDGlobal.hudNumberDuration; // 动画持续时间

        HUDNumberEntry m_ValidList;
        BetterList<int> m_tempNumb = new BetterList<int>();
        private HUDRender m_MeshRender
        {
            get
            {
                if (this.mMeshRender == null)
                {
                    this.mMeshRender = new HUDRender();
                    this.mMeshRender.Initialize();
                }
                return this.mMeshRender;
            }
        }

        HUDRender mMeshRender;

        bool m_bMeshDirty = false;
        //bool m_bCalcCameraScale = false;
        bool m_bCaleScreenScale = false;
        float m_fScreenScaleX = 1.0f;
        float m_fScreenScaleY = 1.0f;

        bool m_enableNumber = true;
        bool m_oldEnableNumber = true;

        float m_scaleValue = 1f;
        bool m_notSamePos = false;

        Camera m_oldCamera;
        // Camera m_renderCamera;
        CommandBuffer s_cmdBuffer = new CommandBuffer();

        private ResLoader mResLoader;

        System.Action m_updateHandle;

        private HUDNumberRender()
        {
            m_updateHandle = () => UpdateLogic(Time.deltaTime);
            HUDRenderPassFeature.GetCmdBuffer = this.GetCmdBuffer;
        }


        public void Initialize(string hudConfigPath, Camera mainCamera = null)
        {
            HUDGlobal.InitHUDSetting(hudConfigPath);
            if (mainCamera != null)
            {
                HUDGlobal.BindHUDMainCamera(mainCamera);
            }
            if (this.mResLoader == null)
            {
                this.mResLoader = ResLoader.Create();
            }

            var rSprite = this.mResLoader.LoadABAsset<Sprite>(PathConstant.GetAtlasSpritePath("HUD/Red", "Red_0"));
            if (rSprite)
            {
                HUDGlobal.BindNumberTexture(rSprite.texture);
            }

            HUDGlobal.AddLateUpdate(m_updateHandle);
        }

        public void Dispose()
        {
            if (this.mResLoader != null)
            {
                this.mResLoader.Put2Pool();
                this.mResLoader = null;
            }

            HUDGlobal.BindNumberTexture(null);
            HUDGlobal.RemoveLateUpate(m_updateHandle);

            while (m_ValidList != null)
            {
                HUDNumberEntry pDel = m_ValidList;
                m_ValidList = m_ValidList.m_pNext;
                OnErase(pDel);
            }

            ReleaseCmmmandBuffer();
            m_MeshRender.Release();
        }

        // exit game dipose
        public void OnLeaveGame()
        {
            this.Dispose();
        }

        void ReleaseCmmmandBuffer()
        {
            if (m_bAddCommandBuffer)
            {
                m_bAddCommandBuffer = false;
                // if (m_renderCamera != null)
                //     m_renderCamera.RemoveCommandBuffer(CameraEvent.AfterImageEffects, s_cmdBuffer);
                // m_renderCamera = null;
                s_cmdBuffer.Clear();
            }
        }

        void CleanCurrentNumber()
        {
            while (m_ValidList != null)
            {
                HUDNumberEntry pDel = m_ValidList;
                m_ValidList = m_ValidList.m_pNext;
                pDel.m_pNext = null;
                OnErase(pDel);
            }

            m_bMeshDirty = true;
        }

        HUDNumberEntry QueryHudNumber(int nType)
        {
            int nIndex = (int)nType;
            HUDNumberEntry pNode = m_aInvalid;
            if (pNode != null)
            {
                m_aInvalid = pNode.m_pNext;
                pNode.m_pNext = null;
            }

            if (pNode == null)
            {
                pNode = new HUDNumberEntry();
                pNode.m_nType = nType;
            }
            return pNode;
        }

        void ReleaseHudNumber(HUDNumberEntry pNode)
        {
            if (pNode != null)
            {
                int nIndex = (int)pNode.m_nType;
                pNode.m_pNext = m_aInvalid;
                m_aInvalid = pNode;
            }
        }

        bool m_bPuase = false;
        float m_currentDuration = 0.0f;

        // 功能：执行数字的动画效果
        void PlayAnimation(HUDNumberEntry pNode, bool bFirst)
        {
            int nIndex = (int)pNode.m_nType;
            HUDUtil.PlayAnimation(pNode, bFirst, HUDGlobal.hudNumSetting[nIndex], m_bPuase, HUDGlobal.numScaleBase,
                m_currentDuration, m_fScreenScaleX, m_fScreenScaleY, m_fDurationTime);
        }

        void OnPush(HUDNumberEntry pNode)
        {
            for (int i = 0; i < pNode.m_aSprite.size; ++i)
            {
                HUDMesh hudMesh = m_MeshRender.QueryMesh(HUDGlobal.numTexture);
                pNode.m_aSprite[i].hudMesh = hudMesh;
                hudMesh.PushHUDVertex(pNode.m_aSprite[i]);
            }
        }

        void OnErase(HUDNumberEntry pNode)
        {
            // 释放模型的数据吧
            pNode.ReleaseVertex();
            ReleaseHudNumber(pNode);
        }

        void FillMeshRender()
        {
            m_MeshRender.FillMesh();
            if (m_MeshRender.m_bMeshDirty)
                m_bMeshDirty = true;
            if (!m_bMeshDirty)
            {
                Camera caMain = HUDGlobal.GetHUDMainCamera();
                if (caMain != m_oldCamera)
                {
                    m_oldCamera = caMain;
                    m_bMeshDirty = true;
                }
            }

            if (m_bMeshDirty)
            {
                m_bMeshDirty = false;

                Camera caMain = HUDGlobal.GetHUDMainCamera();
                s_cmdBuffer.Clear();
                if (caMain == null || !m_enableNumber)
                    return;
                m_MeshRender.RenderTo(s_cmdBuffer);
                if (s_cmdBuffer.sizeInBytes > 0 && caMain != null)
                {
                    m_bAddCommandBuffer = true;
                }
            }
        }

        void CaleScreenScale()
        {
            m_bCaleScreenScale = true;
            m_fScreenScaleX = 1f;//Screen.width / HUDGlobal.DesignScreenWidth;
            m_fScreenScaleY = 1f;//Screen.height / HUDGlobal.DesignScreenHeight;
            m_fScreenScaleX *= HUDMesh.s_fNumberScale;
            m_fScreenScaleY *= HUDMesh.s_fNumberScale;
        }

        void UpdateLogic(float delta)
        {
            // 计算屏幕的缩放
            CaleScreenScale();

            HUDNumberEntry pNode = m_ValidList;
            HUDNumberEntry pLast = m_ValidList;
            while (pNode != null)
            {
                PlayAnimation(pNode, false);
                if (pNode.m_bStop)
                {
                    HUDNumberEntry pDel = pNode;
                    if (pNode == m_ValidList)
                    {
                        m_ValidList = m_ValidList.m_pNext;
                        pLast = m_ValidList;
                    }
                    else
                    {
                        pLast.m_pNext = pNode.m_pNext;
                    }

                    pNode = pNode.m_pNext;
                    OnErase(pDel);
                    continue;
                }

                pLast = pNode;
                pNode = pNode.m_pNext;
            }

            if (m_ValidList == null)
                m_bMeshDirty = true;


            if (m_enableNumber != m_oldEnableNumber)
            {
                m_oldEnableNumber = m_enableNumber;
                m_bMeshDirty = true;
            }

            FillMeshRender();
            if (m_ValidList == null)
            {
                CleanAllMeshRender();
            }
        }

        // 功能：清除所有的模型渲染
        public void CleanAllMeshRender()
        {
            m_MeshRender.FastClearVertex(); // CleanAllVertex
            ReleaseCmmmandBuffer();
        }

        public void AddHudNumber(Vector3 worldPos, Vector3 worldDir, int nType, int nNumber)
        {
            AddHudNumber(worldPos, worldDir, nType, nNumber, Color.white, 1);
        }

        public void AddHudNumber(Vector3 worldPos, Vector3 worldDir, int nType, int nNumber, Color color, float scale = 1f)
        {
            if (!m_enableNumber)
                return;

            if (HUDGlobal.numTexture == null)
                return;

            if (nNumber < 0)
            {
                return;
            }

            //modify
            //Vector3 vPos = tf.position;
            Vector3 vPos = worldPos;

            int nIndex = (int)nType;
            Camera caMain = HUDGlobal.GetHUDMainCamera();
            if (caMain == null)
                return;

            HUDNumberSetting attrib = HUDGlobal.hudNumSetting[nIndex];

            HUDNumberEntry pNode = QueryHudNumber(nType);
            pNode.m_nType = nType;
            pNode.m_pNext = m_ValidList;
            m_ValidList = pNode;

            pNode.reset();

            // 初始化
            pNode.m_nSpriteGap = attrib.SpriteGap;
            pNode.m_fStartTime = Time.time;
            // 暂时不需要实时跟随Transform
            //pNode.m_tf = tf;
            pNode.m_vPos = vPos;
            pNode.m_vMoveDis = attrib.MoveOffset;

            if (caMain != null)
            {
                // 如果按屏幕对齐
                if (attrib.ScreenAlign)
                {
                    Vector3 v1 = caMain.WorldToScreenPoint(vPos);
                    v1.x = attrib.OffsetX;
                    v1.y = attrib.OffsetY;
                    float fScaleX = 1f; //(float) Screen.width / HUDGlobal.DesignScreenWidth;
                    float fScaleY = 1f; //(float) Screen.height / HUDGlobal.DesignScreenHeight;

                    if (attrib.ScreenAlignType == HUDAlignType.align_left)
                    {
                        v1.x = attrib.OffsetX;
                        v1.y = attrib.OffsetY;
                    }
                    else if (attrib.ScreenAlignType == HUDAlignType.align_right)
                    {
                        v1.x = Screen.width - attrib.OffsetX;
                        v1.y = attrib.OffsetY;
                    }
                    else
                    {
                        v1.x = Screen.width / 2.0f + attrib.OffsetX;
                        v1.y = attrib.OffsetY;
                    }

                    v1.x *= fScaleX;
                    v1.y *= fScaleY;

                    pNode.m_vScreenPos = v1;
                    vPos = caMain.ScreenToWorldPoint(v1);
                    pNode.m_vPos = vPos;

                    Vector3 vCameraPos = caMain.transform.position;
                    pNode.CaleCameraScale(vCameraPos, scale,
                        (HUDGlobal.CameraNearDist,
                            HUDGlobal.CameraFarDist,
                            HUDGlobal.NumberScaleMin,
                            HUDGlobal.NumberScaleMax));
                }
                else
                {
                    //同一位置重复跳字，之后的小一点
                    if (!m_notSamePos)
                    {
                        m_scaleValue *= 0.9f;
                        m_scaleValue = Mathf.Max(0.8f, m_scaleValue);
                        scale *= m_scaleValue;
                    }
                    else
                    {
                        m_scaleValue = 1f;
                    }

                    pNode.m_vScreenPos = caMain.WorldToScreenPoint(vPos);
                    Vector3 vCameraPos = caMain.transform.position;
                    pNode.CaleCameraScale(vCameraPos, scale,
                        (HUDGlobal.CameraNearDist,
                            HUDGlobal.CameraFarDist,
                            HUDGlobal.NumberScaleMin,
                            HUDGlobal.NumberScaleMax));
                }
            }

            pNode.m_ScreenDir = ((Vector2)caMain.WorldToScreenPoint(worldPos + worldDir) - (Vector2)caMain.WorldToScreenPoint(worldPos)).normalized;
            float y = 0.0f;
            if (!string.IsNullOrEmpty(attrib.SpriteName))
            {
                pNode.PushSprite(y, this.mResLoader.LoadABAsset<Sprite>(attrib.SpriteName), color);
            }

            if (attrib.ShowNumber)
            {
                m_tempNumb.Clear();
                int nI = 0;
                do
                {
                    nI = nNumber % 10;
                    nNumber /= 10;
                    m_tempNumb.Add(nI);
                } while (nNumber > 0);

                // 反转数组
                m_tempNumb.Reverse();
                for (int i = 0, nSize = m_tempNumb.size; i < nSize; ++i)
                {
                    nI = m_tempNumb[i];
                    pNode.PushSprite(y, this.mResLoader.LoadABAsset<Sprite>(PathConstant.GetAtlasSpritePath("HUD", HUDGlobal.GetSpriteName(nType, nI))), color);
                }
            }

            // 居中处理吧
            switch (attrib.AlignType)
            {
                case HUDAlignType.align_right:
                    pNode.MakeRight();
                    break;
                case HUDAlignType.align_center:
                    pNode.MakeCenter();
                    break;
                default:
                    pNode.MakeLeft();
                    break;
            }

            // 申请纹理
            OnPush(pNode);

            if (!m_bCaleScreenScale)
            {
                CaleScreenScale();
            }

            PlayAnimation(pNode, true);
        }
    }
}